/*
 * Data Transmission thread for XRadio drivers
 *
 * Copyright (c) 2013
 * Xradio Technology Co., Ltd. <www.xradiotech.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef XRADIO_BH_H
#define XRADIO_BH_H

#define XRADIO_BH_THREAD   "xradio_bh"
#define XRADIO_PROC_THREAD "xradio_proc"

/* extern */ struct xradio_common;

#define ITEM_F_RESERVE  0x80  /* use reserved skb */
#define ITEM_F_CMDCFM   0x40  /* cmd confirm packets */
#define ITEM_F_TXCFM    0x20  /* tx confirm packets */

#if BH_PROC_TX
#define BH_WAITING_RX_THRESHOLD  8
#endif

#ifdef BH_PROC_THREAD
struct bh_items {
	struct list_head  head;
	u8                *data;
	u16               datalen;
	u8                if_id;
	u8                flags;
};

#if BH_PROC_DPA
struct thread_dpa {
	int policy;
	int priority;
};
extern u32 proc_dpa_cnt;
extern u32 proc_up_cnt;
extern u32 proc_down_cnt;
#endif
#define ITEM_RESERVED   256
#define PROC_POOL_NUM   8
#define PROC_POOL_SIZE  (sizeof(struct bh_items)*ITEM_RESERVED)
struct bh_proc {
	struct bh_items    *bh_pool[PROC_POOL_NUM];
	struct list_head    bh_free;
	struct list_head    bh_tx;
	struct list_head    bh_rx;
	atomic_t            tx_queued;
	atomic_t            rx_queued;
	atomic_t            proc_tx;
	spinlock_t          lock;
	size_t              txed_num;
	size_t              rxed_num;
	struct task_struct *proc_thread;
	int                 proc_state;
	wait_queue_head_t   proc_wq;
#if BH_PROC_DPA
	s8                  proc_prio;
	s8                  prio_cnt;
#endif
};
int bh_proc_init(struct xradio_common *hw_priv);
void bh_proc_deinit(struct xradio_common *hw_priv);
int bh_proc_reinit(struct xradio_common *hw_priv);
int bh_proc_flush_queue(struct xradio_common *hw_priv);
int bh_proc_flush_txqueue(struct xradio_common *hw_priv, int if_id);
#endif /*BH_PROC_THREAD*/

int xradio_register_bh(struct xradio_common *hw_priv);
void xradio_unregister_bh(struct xradio_common *hw_priv);
void xradio_irq_handler(void *priv);
void xradio_bh_wakeup(struct xradio_common *hw_priv);
int xradio_bh_suspend(struct xradio_common *hw_priv);
int xradio_bh_resume(struct xradio_common *hw_priv);
/* Must be called from BH thread. */
void xradio_enable_powersave(struct xradio_vif *priv, bool enable);
int wsm_release_tx_buffer(struct xradio_common *hw_priv, int count);
int wsm_release_vif_tx_buffer(struct xradio_common *hw_priv, int if_id,
			      int count);
int xradio_init_resv_skb(struct xradio_common *hw_priv);
void xradio_deinit_resv_skb(struct xradio_common *hw_priv);
int xradio_realloc_resv_skb(struct xradio_common *hw_priv,
							struct sk_buff *skb, u8 flags);

#ifdef BH_PROC_THREAD
void xradio_proc_wakeup(struct xradio_common *hw_priv);
#else
static inline void xradio_proc_wakeup(struct xradio_common *hw_priv)
{
	xradio_bh_wakeup(hw_priv);
}
#endif

#endif /* XRADIO_BH_H */
